#pragma once

#include "../opengl/buffer.h"
#include "../texturegroup.h"
#include "mesh.h"
#include "boundingbox.h"

namespace GLC {

class CModelMaterial;

class Model : boost::noncopyable
{
public:
    Model(void);

    /************************************************************************/
    /* Работа с полигональными сетками                                      */
    /************************************************************************/

    // Получаем полигональную сетку, входящую в модель по ее индексу
    Mesh const& GetMesh(size_t index)const;
    Mesh & GetMesh(size_t index);

    // Получаем количество полигональных сеток в модели
    size_t GetMeshCount()const;

    // Добавляем полигональную сетку к модели
    Mesh & AddMesh(unsigned int vertexBufferOffset,
        unsigned int indexBufferOffset,
        unsigned vertexCount,
        unsigned indexCount,
        bool hasTexture,
        BoundingBox const& boundingBox,
        GLenum primitiveType,
        GLenum indexType
    );

    /************************************************************************/
    /* Работа с ограничивающим блоком модели                                */
    /************************************************************************/

    // Получаем bounding box, ограничивающий трехмерную модель
    BoundingBox const GetBoundingBox()const;

    /************************************************************************/
    /* Работа с текстурами модели                                           */
    /************************************************************************/

    // Добавляем текстурное изображение
    Texture2DRef AddTextureImage(std::string const& name);

    // Возвращаем количество текстур
    size_t GetTexturesCount()const;

    // Возвращаем имя текстурного изображения по его индексу
//    std::string GetTextureName(size_t index) const;

    // Есть ли текстура с данным именем?
    bool HasTexture(std::string const& name) const;

    // Возвращаем текстурный объект по его имени
    Texture2DRef GetTextureByName(std::string const& name) const;

    // Возвращаем текстурный объект по его индексу
    Texture2DRef GetTexture(size_t index) const;

    /************************************************************************/
    /* Работа с материалами модели                                          */
    /************************************************************************/

    // Добавляем материал
    CModelMaterial & AddMaterial();

    // Получаем количество материалов
    size_t GetMeterialCount()const;

    // Получаем материал по его индексу
    CModelMaterial const & GetMaterial(size_t index)const;
    CModelMaterial & GetMaterial(size_t index);

    /************************************************************************/
    /* Работа с буферами вершин и индексов                                  */
    /************************************************************************/

    // Получаем вершинный буфер
    CVertexBuffer & GetVertexBuffer();
    CVertexBuffer const& GetVertexBuffer()const;

    // Получаем индексный буфер
    CIndexBuffer & GetIndexBuffer();
    CIndexBuffer const & GetIndexBuffer()const;

private:
    // Вершинный и индексный буферы
    CVertexBuffer	m_vertexBuffer;
    CIndexBuffer	m_indexBuffer;

    TextureGroup m_textures;
    // Материалы модели
    typedef std::shared_ptr<CModelMaterial> CModelMaterialPtr;
    std::vector<CModelMaterialPtr> m_materials;

    // полигональные сетки модели
    typedef std::shared_ptr<Mesh> CMeshPtr;
    std::vector<CMeshPtr> m_meshes;

    // Флаг, сигнализирующий о необходимости перевычисления
    // ограничивающего блока модели
    mutable bool m_boundingBoxMustBeUpdated;
    // Ограничивающий блок модели
    mutable BoundingBox m_boundingBox;
};

} // namespace GLC
